<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 分析题目描述
        // 1. 如果开头是空格，忽略这个空格
        // 2. 如果检测完空格，紧接着检测是否是负数，如果检测到-号，最终要转化为负数 不然就是正数 默认
        // 3. 如果下一个字符是非数字，就停止读，非数字不能放进去
        // 4. 如果一个数字都没有，就返回0
        // 5. 如果正数 超过 2^31-1 就固定为2^31-1 Math.pow(2,31)
        // 6. 如果负数 小于 -2^31  就固定为 -2^31 - Math.pow(2,31)

        // 用例：
        // "42" 42
        // "   -42" -42
        // "4193 with words" 4193
        // "words and 987" 0 
        // "-91283472332" -2147483648

        // 逻辑顺序
        // 1、长度为0
        // 2、去除前导空格
        // 3、前置符号判断
        // 4、非数字判断
        // 5、是否溢出判断
        // 6、取出字符变成整数的算法
        var myAtoi = function(s) {
            const n = s.length - 1  // 字符串长度
            let index = 0 // 遍历的第几位字符串
            let res = 0 //最终结果 如果没有数字 最终return res 就是0
            let sign = 1  // 符号 默认是正的
            const max = Math.pow(2,31) - 1
            const min = - Math.pow(2,31)
            // 1、如果长度为0 就返回0
            if(s.length === 0) {
                return 0
            }
            ///2、去空格
            while(s[index] === ' ') {
                index++
            } 
            ///3、前置符号判断
            if(s[index] === '+') {
                sign = 1 // 如果是+号index就+1
                index++
            } else if(s[index] === '-') {
                sign = -1 // 如果是减号 index+1并且signWie-1
                index++
            }

            ///4、遍历字符
            let temp = 0
            while(index <= n) {
                if(s[index] === ' ') {
                    debugger
                    return res * sign
                }
                ///4、非数字判断
                // let num = s[index] - '0' // 转化为整数
                // 这里运用了s.charCodeAt(index) 判断是否是整数 如果是 Unicode码要在48 57之间
                if(!(s.charCodeAt(index) >= 48 && s.charCodeAt(index) <= 57)) {
                    return res * sign
                }
                let num = s[index] - '0' // 转化为整数
                // 如果是非数字 上面运算是NaN 下面的条件一定会满足一个
                // NaN < 0 => false => !false 就是 true
                // 3 > 0 => true => !true 就是false

                // 易错1：这里如果写(!num >= 0 || !num <= 9 就会报错
                // !逻辑非的优先级大于比较运算符
                // 如果是非数字 - '0' => NaN => !NaN是true => true >= 0 是true
                // 如果是数字 比如 !3 => false => false >= 0 也是true 这样就区分不开数字还是非数字 都进入了if循环
                // 而!(num >= 0) => NaN >= 0 || NaN <= 0 都是false 取反就是true 进入if循环
                // 而3 >= 0 || 3 <= 9 都是 true 整体取反就是false 不进入

                // 易错2：num >=0 还是num > 0 应该是 num >=0 不然字符串 => "21474836460" 就会通过不过测试用例，0应该算进去 最终溢出 取2147483647 => max
                // 但是此时，"4193 with words"这个用例通过不了 原因是
                // ' ' - '0' 空字符串 减去 字符串'0' 结果是数字 0 下面if语句不会进入，可是题目要求只去除 前导空格，中间后置的空格是会算入的 因此while语句后面增加判断
                // 易错3: 溢出 | 碰到空格或者非字符时 return res 都记得乘以 sign符号

                // if(!(num >= 0) || !(num <= 9)) {
                //     return res * sign
                // }
                
                res = res * 10 + num 
                if(res * sign >= max) {
                    return max 
                } else if(res * sign <= min) {
                    return min
                }
                index++
            }
            return  sign * res            
        }
        // 探索1： charCodeAt(i)
        // 探索2： 如何判断溢出
        console.log(myAtoi('-123456abccba'));
        console.log(myAtoi("4193 with words"));
        console.log(myAtoi("-91283472332"));
        // JS的最大安全数：-2^ 53 ~ Math.pow(2, 53) - 1，即 9007199254740991
        // 这个之间
        // Math.pow(2, 53) === Math.pow(2, 53) + 1 true
        // 对应同一个双精度数 因此 Math.pow(2, 53) 不是安全数

        // 173.8125 转化位二进制 整数 除2取余逆序排列 小数部分 ×2取整 正序排列
        // 0.1 转化为二进制会无限循环 丢失了精度  0.5 不会丢失
        // 为什么会丢失精度？0.1 + 0.2 为什么 不等于0.3 而是0.30000000000000004
        // 因为 转化为二进制会无限循环
        // 为什么会无限循环？
        // 来自公式

        



        // 解法2：
        // const NUMBERS = "0123456789";
        // const MIN = -Math.pow(2,31);
        // const MAX = Math.pow(2,31) - 1;
        // var myAtoi = function (str) {
        //     str = str.trim();
        //     let arr = str.split(""),
        //         flag = "+",
        //         result = "0";
        //     try {
        //         arr.forEach((item, index) => {
        //             if (index === 0) {
        //                 if (item === "-") {
        //                     flag = "-";
        //                 } else if (item === "+") {
        //                     flag = "+";
        //                 } else if (NUMBERS.indexOf(item) === -1) {
        //                     throw new Error("break");
        //                 } else {
        //                     result = result + item;
        //                 }
        //             } else {
        //                 if (NUMBERS.indexOf(item) === -1) {
        //                     throw new Error("break");
        //                 } else {
        //                     result = result + item;
        //                 }
        //             }
        //         })
        //     } catch (error) {
        //         console.log("error", error);
        //     }
        //     result = parseInt(flag + result);
        //     if (result < MIN) {
        //         result = MIN;
        //     } else if (result > MAX) {
        //         result = MAX;
        //     }
        //     return result;
        // }
    </script>
    
</body>
</html>